<?php 
// Connect, query, fetch, .... mySQL
class __DATABASE {
	private static $_instance;
	private $connection = false;
	private $dbhost;
	private $dbuser;
	private $dbpass;
	private $dbname;
	private $last_result = false;
	public $fatal_error = false;
	private $debug_mode = false;
	private $debug_info = false;
	private $ext;
	public $disconnect_on_descruct;

	public function getInstance($databaseSetting)
	{
		if (!self::$_instance) self::$_instance = new self($databaseSetting);

		return self::$_instance;
	}

	public function __construct($databaseSetting)
	{
		$this->_setup($databaseSetting);
	}

	private function _setup($databaseSetting)
	{
		if ($databaseSetting['host']) $this->dbhost = $databaseSetting['host'];
		if ($databaseSetting['username']) $this->dbuser = $databaseSetting['username'];
		if ($databaseSetting['password']) $this->dbpass = $databaseSetting['password'];
		if ($databaseSetting['dbName']) $this->dbname = $databaseSetting['dbName'];
		$this->debug_mode = $databaseSetting['debugs'];
		$this->debug_info = & $GLOBALS['MYSQL_DEBUG_INFO'];
		$this->ext = 'mysql';
		if (isset($databaseSetting['databaseExtended']) AND $databaseSetting['databaseExtended'] == 'mysqli')
		{
			$this->ext = 'mysqli';
		}
		$this->disconnect_on_descruct = TRUE;
	}

	public function connect()
	{
		$time	= microtime(TRUE);
		$this->connection	= $this->ext=='mysqli' ? @mysqli_connect($this->dbhost, $this->dbuser, $this->dbpass) : @mysql_connect($this->dbhost, $this->dbuser, $this->dbpass);
		if(FALSE == $this->connection)
		{
			return $this->fatal_error('Connect');
		}
		$db	= $this->ext=='mysqli' ? mysqli_select_db($this->connection, $this->dbname) : mysql_select_db($this->dbname, $this->connection);
		if(FALSE == $db)
		{
			return $this->fatal_error('Select DB');
		}
		$this->ext=='mysqli' ? @mysqli_query($this->connection, 'SET NAMES utf8') : @mysql_query('SET NAMES utf8', $this->connection);
		if($this->debug_mode)
		{
			$time	= microtime(TRUE) - $time;
			$this->debug_info->queries[] = (object) array (
				'query'	=> 'CONNECT '.$this->dbhost,
				'time'	=> number_format($time, 5, '.', ''),
			);
			$this->debug_info->time += $time;
		}
		return $this->connection;
	}

	private function fatal_error($query)
	{
		$this->fatal_error = TRUE;
		$error = $this->ext=='mysqli' ? mysqli_error() : mysql_error();
		if($this->debug_mode)
		{
			echo 'MySQL Query: ' . $query . '<br />';
			echo 'MySQL Error: ' . $error . '<br />';
			exit;
		}
		exit;
		//return FALSE;
	}

	public function query($query, $remember_result = TRUE)
	{
		if(FALSE == $this->connection)
		{
			$this->connect();
		}
		$time = microtime(TRUE);
		$result = $this->ext=='mysqli' ? mysqli_query($this->connection, $query) : mysql_query($query, $this->connection);
		if($this->debug_mode)
		{
			$time = microtime(TRUE) - $time;
			$this->debug_info->queries[] = (object) array (
				'query'	=> $query,
				'time'	=> number_format($time, 5, '.', ''),
			);
			$this->debug_info->time += $time;
		}
		if(FALSE == $result)
		{
			return $this->fatal_error($query);
		}
		if($remember_result)
		{
			$this->last_result = $result;
		}
		return $result;
	}

	public function q($query, $remember_result = TRUE)
	{
		return $this->query($query, $remember_result);
	}

	public function fetch_object($res=FALSE)
	{
		$res	= FALSE!==$res ? $res : $this->last_result;
		if(FALSE == $res)
		{
			return FALSE;
		}

		return $this->ext=='mysqli' ? mysqli_fetch_object($res) : mysql_fetch_object($res);
	}

	public function fetchrow($res=FALSE, $type = 0)
	{
		$res	= FALSE!==$res ? $res : $this->last_result;
		if(FALSE == $res)
		{
			return FALSE;
		}

		if ($type != 1 and $type != 2) $type = 0;
		switch ($type)
		{
			case 1: return $this->ext=='mysqli' ? @mysqli_fetch_array($res, MYSQL_NUM) : @mysql_fetch_array($res, MYSQL_NUM); break;
			case 2: return $this->ext=='mysqli' ? @mysqli_fetch_array($res, MYSQL_ASSOC ) : @mysql_fetch_array($res, MYSQL_ASSOC); break;
			default: return $this->ext=='mysqli' ? @mysqli_fetch_array($res, MYSQL_BOTH ) : @mysql_fetch_array($res, MYSQL_BOTH);
		}
		return false;
	}

	public function fetchAssoc($res=FALSE)
	{
		$res	= FALSE!==$res ? $res : $this->last_result;
		if(FALSE == $res)
		{
			return FALSE;
		}
		return $this->ext=='mysqli' ? @mysqli_fetch_assoc($res) : @mysql_fetch_assoc($res);
		return false;
	}

	public function fObject($res=FALSE)
	{
		return $this->fetch_object($res);
	}

	public function fetch($query)
	{
		$res	= $this->query($query, FALSE);
		if(FALSE == $res) {
			return FALSE;
		}
		return $this->fetch_object($res);
	}

	public function f($query)
	{
		return $this->fetch($query);
	}

	public function fetch_all($query)
	{
		$res = $this->query($query, FALSE);
		if (FALSE == $res)
		{
			return FALSE;
		}
		$data = array();
		while ($obj = $this->fetch_object($res))
		{
			$data[] = $obj;
		}
		$this->free_result($res);
		return $data;
	}

	public function fetch_field($query)
	{
		$res	= $this->query($query, FALSE);
		if(FALSE == $res) {
			return FALSE;
		}
		if( ! $row = ( $this->ext=='mysqli' ? mysqli_fetch_row($res) : mysql_fetch_row($res) ) ) {
			return FALSE;
		}
		$this->free_result($res);
		return $row[0];
	}

	public function num_rows($res=FALSE)
	{
		$res    = FALSE!==$res ? $res : $this->last_result;
		if(FALSE == $res) {
			return FALSE;
		}
		return $this->ext=='mysqli' ? mysqli_num_rows($res) : mysql_num_rows($res);
	}

	public function nums($res=FALSE)
	{
		return $this->num_rows($res);
	}

	public function insert_id()
	{
		if(FALSE == $this->connection)
		{
			$this->connect();
		}
		return intval( $this->ext=='mysqli' ? mysqli_insert_id($this->connection) : mysql_insert_id($this->connection) );
	}

	public function insertID()
	{
		return $this->insert_id();
	}

	public function affected_rows()
	{
		if(FALSE == $this->connection)
		{
			$this->connect();
		}
		return $this->ext=='mysqli' ? mysqli_affected_rows($this->connection) : mysql_affected_rows($this->connection);
	}

	public function affectedRows()
	{
		return $this->affected_rows();
	}

	public function data_seek($row=0, $res=FALSE)
	{
		$res    = FALSE!==$res ? $res : $this->last_result;
		if(FALSE == $res)
		{
			return FALSE;
		}
		return $this->ext=='mysqli' ? mysqli_data_seek($res, $row) : mysql_data_seek($res, $row);
	}

	public function dataSeek($row=0, $res=FALSE)
	{
		return $this->data_seek($row, $res);
	}

	public function free_result($res=FALSE)
	{
		$res    = FALSE!==$res ? $res : $this->last_result;
		if(FALSE == $res)
		{
			return FALSE;
		}
		return $this->ext=='mysqli' ? mysqli_free_result($res) : mysql_free_result($res);
	}

	public function free($res=FALSE)
	{
		return $this->free_result($res);
	}

	public function escape($string)
	{
		if(FALSE == $this->connection)
		{
			$this->connect();
		}
		return $this->ext=='mysqli' ? mysqli_real_escape_string($this->connection, $string) : mysql_real_escape_string($string, $this->connection);
	}

	public function e($string)
	{
		return $this->escape($string);
	}

	public function getDebugInfo()
	{
		$debug_info = clone($this->debug_info);
		$debug_info->time = number_format($debug_info->time, 4, '.', '');
		$debug_info->queries = array_reverse($debug_info->queries);
		return $debug_info;
	}

	public function deleteDebugInfo()
	{
		$this->debug_info->queries = array();
	}

	public function __destruct()
	{
		if ($this->disconnect_on_descruct)
		{
			if ($this->connection)
			{
				$this->ext=='mysqli' ? @mysqli_close($this->connection) : @mysql_close($this->connection);
				$this->connection = FALSE;
			}
		}
	}
}

